<?php
// +----------------------------------------------------------------------
// | 杭州十禾信息科技有限公司
// +----------------------------------------------------------------------
// | Copyright (c) 2013-2015 http://www.shelpe.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: LeePuman <ysyzlsm@163.com>
// +----------------------------------------------------------------------

class AdgroupModel extends NewzanModel{

	protected $tableName = 'adgroups';
    
	/* table columns */
    protected $fields = array(

    );

	/* validations definitions */

    protected $_validate = array(
        
    );

    protected $_auto = array(

    );

    /** log对应的操作 */
    protected $action_names = array(
    		AdgroupLogActions::AUTO_ADD => '添加推广组',
    		AdgroupLogActions::AUTO_DEL => '删除推广组',
    		AdgroupLogActions::AUTO_PAUSE => '暂停推广组',
    		AdgroupLogActions::AUTO_OPEN => '开启推广组',
    		AdgroupLogActions::AUTO_UPDATE => '修改推广组设置',
    		AdgroupLogActions::AUTO_UPDATE_CATMATCH => '修改推广组类目出价',
    		AdgroupLogActions::MANUAL_ADD => '添加推广组',
    		AdgroupLogActions::MANUAL_DEL => '删除推广组',
    		AdgroupLogActions::MANUAL_OPEN => '开启推广组',
    		AdgroupLogActions::MANUAL_PAUSE => '暂停推广组',
    		AdgroupLogActions::MANUAL_UPDATE => '修改推广组设置',
    		AdgroupLogActions::MANUAL_UPDATE_CATMATCH => '修改推广组类目出价',
    		AdgroupLogActions::SWITCH_DRIVE_TYPE => '开车类型切换',
    );
    
    /** @var Model 删除掉的推广组, 备份 */
    protected $_deletedMdl = null;
    /** @var Model 日志Model */
    protected $_logMdl = null;
    
    /** @var int 开车类型: 自动 */
    const DRIVE_TYPE_AUTO = 1;
    /** @var int 开车类型: 手动 */
    const DRIVE_TYPE_MANUAL = 0;
    /** @var int 当前状态为空闲, 可进行任意操作 */
    const STATUS_IDLE = 0;
    /** @var int 当前状态为正在自动更新, 不可进行任何手动操作. 在自动转化为手动的时候需要检查此项. */
    const STATUS_UPDATING =1;
    /** @var int 当前状态为暂停. */
    const STATUS_PAUSED =2;
    /** @var int 当前状态为自动提交后,等待用户确认 */
    const STATUS_WAITING_CONFIRM = -1;
    /** @var int 空白状态 */
    const STATUS_BLANK = -9;
    
    public function getForAdgroupIndex($user_id, $index = 'impressions', $type = 'MAX', $from, $to, $ids, $data_source)
    {
        if(is_array($ids)) {
            $ids = implode(',', $ids);
        }
        if($type == "AVG") {
            $sql = "SELECT 
                        k.keyword_id,rpt.impressions,rpt.click,rpt.cost,
                        rpt.sales,rpt.cvr,rpt.ctr,rpt.cpc,rpt.cpm,rpt.avgpos,
                        rpt.roi,rpt.fav_count,rpt.fav_count_rate,rpt.cart_total,
                        rpt.cart_total_rate,rpt.total_pay_count,FORMAT(AVG(k.qscore), 0) AS qscore,FORMAT(AVG(k.wireless_qscore), 0) AS wireless_qscore
                    FROM
                        (SELECT keyword_id, 
                            SUM(impressions) AS impressions,SUM(click) AS click,SUM(cost)/100 AS cost,
                            SUM(direct_pay + indirect_pay)/100 AS sales,
                            100*SUM(direct_pay_count + indirect_pay_count)/SUM(click) AS cvr,
                            100*SUM(click)/SUM(impressions) AS ctr, 
                            SUM(cost)/100/SUM(click) AS cpc, 
                            10*SUM(cost)/SUM(impressions) AS cpm,
                            AVG(avgpos) AS avgpos,
                            SUM(direct_pay + indirect_pay)/SUM(cost) AS roi,
                            SUM(fav_item_count + fav_shop_count) AS fav_count,
                            (SUM(fav_item_count + fav_shop_count)/SUM(click))*100 AS fav_count_rate,
                            SUM(cart_total) as cart_total,
                            (SUM(cart_total)/SUM(click))*100 AS cart_total_rate,
                            SUM(direct_pay_count + indirect_pay_count) AS total_pay_count
                        FROM `rpt_keyword{$user_id}` 
                        WHERE adgroup_id IN({$ids}) AND `date` BETWEEN '{$from}' AND '{$to}' AND source IN ".($data_source == 1 ? '(1,2)' : '(4,5)')." GROUP BY keyword_id) AS rpt 
                    RIGHT JOIN `keywords{$user_id}` AS k ON rpt.keyword_id = k.keyword_id
                    LEFT JOIN adgroups AS Ad ON Ad.adgroup_id = k.adgroup_id
                    WHERE
                        k.adgroup_id IN({$ids})
                    GROUP BY keyword_id";
            $res = $this->query($sql);
            $avg = getKeywordIndexAvg($res);
            return $avg;
            // return $avg[$index];
        } else {
            $sql = "SELECT 
                        MAX(impressions) AS impressions,MAX(click) AS click,
                        MAX(cost) AS cost,MAX(sales) AS sales,MAX(cvr) AS cvr,
                        MAX(ctr) AS ctr,MAX(cpc) AS cpc,MAX(cpm) AS cpm,
                        MAX(avgpos) AS avgpos,MAX(roi) AS roi,MAX(fav_count) AS fav_count,
                        MAX(fav_count_rate) AS fav_count_rate,MAX(cart_total) AS cart_total,
                        MAX(cart_total_rate) AS cart_total_rate, MAX(total_pay_count) AS total_pay_count,
                        MAX(k.qscore) AS qscore, MAX(k.wireless_qscore) AS wireless_qscore
                    FROM
                        (SELECT keyword_id, 
                            SUM(impressions) AS impressions,SUM(click) AS click,SUM(cost)/100 AS cost,
                            SUM(direct_pay + indirect_pay)/100 AS sales,
                            100*SUM(direct_pay_count + indirect_pay_count)/SUM(click) AS cvr,
                            100*SUM(click)/SUM(impressions) AS ctr, 
                            SUM(cost)/100/SUM(click) AS cpc, 
                            10*SUM(cost)/SUM(impressions) AS cpm,
                            AVG(avgpos) AS avgpos,
                            SUM(direct_pay + indirect_pay)/SUM(cost) AS roi,
                            SUM(fav_item_count + fav_shop_count) AS fav_count,
                            (SUM(fav_item_count + fav_shop_count)/SUM(click))*100 AS fav_count_rate,
                            SUM(cart_total) as cart_total,
                            (SUM(cart_total)/SUM(click))*100 AS cart_total_rate,
                            SUM(direct_pay_count + indirect_pay_count) AS total_pay_count
                        FROM `rpt_keyword{$user_id}` 
                        WHERE adgroup_id IN({$ids}) AND `date` BETWEEN '{$from}' AND '{$to}' AND source IN ".($data_source == 1 ? '(1,2)' : '(4,5)')." GROUP BY keyword_id) AS rpt
                    RIGHT JOIN `keywords{$user_id}` AS k ON rpt.keyword_id = k.keyword_id";
            $res = $this->query($sql);
            return $res[0];
        }
        
    }

    /**
     * 获取某个用户的全部自动开车的推广组.
     * 
     * TODO 也需要排除已经暂停超过3天的推广组
     * 
     * @param int $userId 用户淘宝ID
     * @param int(>=0) $days = 2 天数.只查找给定的天数以内没有被维护过的推广组. 相当于每$days维护一次.
     * @param int $status = self::STATUS_IDLE 状态.只查找为给定状态的推广组
     * @return false|array2D 当sql执行出错时返回false, 否则返回二维数组结果.
     */
    public function getAutodriveAdgroups($userId, $days = 2, $status = self::STATUS_IDLE) {
    	return $this->where(array(
    			'user_id' => $userId, 
    			'drive_type' => self::DRIVE_TYPE_AUTO,
    			'status' => $status,
    			'online_status' => 'online',
    			'maintained_date' => array('elt', date('Y-m-d', strtotime("-$days day"))),
//     			'create_time' => array('elt', date('Y-m-d', strtotime("-$days day"))),
    	))->select();
    }

    /**
     * 获取存在需自动更新adgroup的用户列表
     * @param int(>=0) $days = 2 天数.只查找给定的天数以内没有被维护过的推广组. 相当于每$days维护一次.
     * @param int $status = self::STATUS_IDLE 状态.只查找为给定状态的推广组
     * @param int $batchSize 每次更新的adgroup大小
     * @return array(int) 返回用户ID列表。
     * 
     * select  DISTINCT a.user_id FROM `adgroups` a 
INNER JOIN users u ON a.user_id=u.user_id 
INNER JOIN auto_pro_product_queue q ON a.user_id = q.user_id
WHERE ( a.`drive_type` = 1 ) AND ( a.`status` = 0 ) AND ( a.`online_status` = 'online' ) 
	AND ( (q.`type`<4 AND a.`maintained_date` <= '2013-10-31') || (q.`type`=4 AND a.`maintained_date` <= '2013-10-29') ) 
	AND u.purchase_expires > '2013-11-02'
LIMIT 50;

     */
    public function getValidAutoUserIds($days = 2, $status = self::STATUS_IDLE, $batchSize = 50) {
    	/*return $this->where(array(
    			'drive_type' => self::DRIVE_TYPE_AUTO,
    			'status' => $status,
    			'online_status' => 'online',
    			'maintained_date' => array('elt', date('Y-m-d', strtotime("-$days day"))),
    			//     			'create_time' => array('elt', date('Y-m-d', strtotime("-$days day"))),
    	))->limit($batchSize)->distinct(true)->getField('user_id', true);
    	*/
    	
    	$minDays = date('Y-m-d', strtotime('-' . min(AutoDriveBaseModel::$MAINTAIN_PERIOD) . ' days'));
    	$maxDays = date('Y-m-d', strtotime('-' . max(AutoDriveBaseModel::$MAINTAIN_PERIOD) . ' days'));
    	$today = date('Y-m-d');
    	$superSaveMode = 4; // 超省油广撒网计划
    	
//      $sql = "SELECT DISTINCT u.user_id FROM `users` u 
// INNER JOIN adgroups a ON u.user_id=a.user_id 
// INNER JOIN auto_pro_product_queue q ON u.user_id = q.user_id 
// WHERE ( a.`drive_type` = 1 ) AND ( a.`status` = $status ) AND ( a.`online_status` = 'online' ) 
//  AND ( (q.`type` <> $superSaveMode AND a.`maintained_date` <= '$minDays') || (q.`type` = $superSaveMode AND a.`maintained_date` <= '$maxDays') ) 
// LIMIT $batchSize";
    	$sql = "SELECT DISTINCT u.user_id FROM `users` u 
INNER JOIN adgroups a ON u.user_id=a.user_id 
INNER JOIN auto_pro_product_queue q ON u.user_id = q.user_id 
WHERE ( a.`drive_type` = 1 ) AND ( a.`status` = $status ) AND ( a.`online_status` = 'online' ) 
LIMIT $batchSize";
		$rawRes = $this->query($sql);
		$finalRes = array();
		foreach($rawRes as $row) {
			$finalRes[] = $row['user_id'];
		}
		return $finalRes;
    }
    
    
    /**
     * 更新推广组的状态. 
     * <strong>注意:</strong> 调用之前需确认该推广组属于正在操作的用户.
     * 
     * @param int $adgroupId Adgroup ID.
     * @param int $status AdgroupModel::STATUS_IDLE or AdgroupModel::STATUS_UPDATING
     * @param int $ori_status 如果给定原来的状态, 检查现在状态. 如果已经被其他进程改变, 则当前进程不再改变.
     * 		比如: 当前进程正在进行自动更新, 但是同时人为暂停了当前adgrop, 那么就不能把状态再更新为idle, 而应保持为paused.
     * @param bool $setMaintainDate 是否设置maintained_date为今天.
     * @return false|int 如果查询错误或者数据非法返回false; 如果更新成功返回影响的记录数
     */
    public function updateStatus($adgroupId, $status, $ori_status = self::STATUS_BLANK, $setMaintainDate = false) {
    	$data =array('status' => $status);
    	if($setMaintainDate) {
    		$data['maintained_date'] = date('Y-m-d');
    	}
    	$where = array('adgroup_id' => $adgroupId);
    	if($ori_status != self::STATUS_BLANK) {
    		$where['status'] = $ori_status;
    	}
    	return $this->where($where)->save($data);
    }
    
    /**
     * 删除一个推广组. 从直通车删除, 同时从本地DB中删除.
     *   
     * @param int $user_id 
     * @param int $adgroup_id 
     * @param boolean $isAutodrive
     * @return false|int 如果删除失败(比如推广组不属于该用户), 则返回false; 否则返回删除的记录数. 
     * @throws TopClientException 当执行API失败的时候, 会抛出异常.
     */
    public function removeAdgroup($userId, $adgroupId, $isAutodrive = false) {
    	if(!$adgroupId) 
    		return false;
    	
    	$adgroup = null;
    	try {
	        $resp = $this->removeAdroupByApi($adgroupId); 
	        $adgroup = (array) $resp["adgroup"];
	   	} catch (TopClientException $topEx) {
        	// 如果是已经直通车上已经删除的推广组, 从本地数据库也删除
        	$oEx = json_decode($topEx->getMessage(), true);
        	if($oEx['error_response']['sub_msg'] == '指定的推广组不存在') {
        		$adgroup = $this->getAdgroupByAdgroupId($userId, $adgroupId, false);
        	} else {
                throw new TopClientException($oEx['error_response']['msg'], 1);
            }
        }
        
        if($adgroup){
        	$this->addLog($adgroupId, $adgroup['campaign_id'], 
        			($isAutodrive ? AdgroupLogActions::AUTO_DEL : AdgroupLogActions::MANUAL_DEL),
        			0);
        	
        	return $this->removeAdgroupFromDb($userId, $adgroupId, $adgroup['campaign_id']); //, new ApiModel(), $isAutodrive
        } else {
	        return false;
        }
    	
    }
    
    /**
     * 单纯调用API将给定adgroup从直通车删除.
     * @param int $adgroupId
     */
    public function removeAdroupByApi($adgroupId) {
    	return $this->_api->SimbaAdgroupDeleteRequest( array("adgroup_id" => $adgroupId) ); 
    }

    /**
     * 从DB中删除该推广组以及该推广组的所有keywords. 不记录log.
     * 同时检查该推广组是否存在于 auto_pro_product_queue 表中, 如果存在也删掉.
     * 
     * @param int $userId 主要用来检查权限. 
     * @param int $adgroupId
     * @param int $campaignId
     * @return ThinkPhp中Model::delete()的返回值.
     */
    public function removeAdgroupFromDb($userId, $adgroupId, $campaignId) {
    	
    	// 先从auto_pro_product_queue删除(如果存在的话)
    	D('ProductQueue')->removeRecord($userId, ProductQueueAct::MANUAL_DEL, 
    			0, 0, $adgroupId, true);
    	 
    	// 从DB中删除该推广组的所有keywords 
    	$keywordMdl = new KeywordModel();
    	$keywordIds = $keywordMdl->field('GROUP_CONCAT(keyword_id)')
    			->where(array('adgroup_id' => $adgroupId))
    			->getField('GROUP_CONCAT(keyword_id)');
    	if(!empty($keywordIds)){
    		$keywordMdl->deleteKeywordsFromDb($keywordIds, $campaignId ? $campaignId : $adgroup['campaign_id']);
    	}
    	//remove creative
    	$creativeMdl=new CreativeModel;
    	$creatives=$creativeMdl->getCreativesByAdgroupId($userId , $adgroupId,false);
    	foreach($creatives as $creative){
			// 备份记录
    		M('creatives_deleted')->add($creative, array(), true);
    		
	    	// 删除
	    	M('creatives')->where( array( "adgroup_id" => $adgroupId ) )->delete();
	    	
	    	// 记录log
	    	$creativeMdl->addLog($creative['creative_id'], $creative['adgroup_id'], CreativeLogActions::MANUAL_DEL);
    	}
    	
    	//同时删除相关同步数据
     /*   $whr = array(
			'user_id' => $userId,
			'entity' => 'rpt-adgroup:'.$adgroupId,
		);
        M('sync_status')->where($whr)->delete();
        $whr = array(
			'user_id' => $userId,
			'entity' => 'adgroup-keyword:'.$adgroupId,
		);
        M('sync_status')->where($whr)->delete();*/
        $whr = array(
			'user_id' => $userId,
			'entity' =>  array('like','%'.$adgroupId.'%'),
		);
       M('sync_status')->where($whr)->delete();
    	
       // 准备删除adgroup
    	$whr = array(
    			'user_id' => $userId,
    			'adgroup_id' => $adgroupId
    	);
    	$adgroup = $this->where($whr)->find();
    	if(!$adgroup)
    		return false;
    	 
    	// 将adgroup从表adgroups移至adgroups_deleted中
    	$this->_getDeletedMdl()->add($adgroup, '', true);
    	$this->where( $whr )->delete(); 
    	 
    	return true;
    }
    
    /** 
     * 暂停或开启一个推广组
     * @param int $user_id user id
     * @param int $adgroup_id params 
     * @param string $online_status online|offline
     * @param bool $isAutodrive
     * @return bool the catmatch record 
     */
    public function pauseOrOpenAdgroup($user_id , $adgroup_id , $online_status = 'offline', $isAutodrive = false) {
    	$data = array(
    			'online_status' => $online_status
    	);
    	return $this->updateAdgroup($user_id, $adgroup_id, $data, $isAutodrive);
    	
        /* $params = array(
            'adgroup_id' => $adgroup_id,
            'online_status' => $online_status
        );
        $res = $this->_api->SimbaAdgroupUpdateRequest($params); 
        $adgroup = (array) $res["adgroup"];
        if($adgroup){
        	$this->addLog($adgroup_id, $adgroup['campaign_id'], 
        			($isAutodrive ? ($online_status == 'offline' ? AdgroupLogActions::AUTO_PAUSE : AdgroupLogActions::AUTO_OPEN)
        					: ($online_status == 'offline' ? AdgroupLogActions::MANUAL_PAUSE : AdgroupLogActions::MANUAL_OPEN)
        			)
       		);
        	
            $whr = array(
                'user_id' => $user_id,
                'adgroup_id' => $adgroup_id
            );
            $data = array(
            		'status' => ($online_status == 'offline' ? 2 : 0),
            		'online_status' => $online_status
            	);
            $ret = $this->where( $whr )->save($data);
        }
        return  true; */
    }    
    
    /** 
     * 更新一个推广组的类目出价，可以设置类目出价、是否使用默认出价、是否打开类目出价.
     * 记录log, log中的新值为新的出价.
     * 
     * 
     * @params int $user_id user id
     * @params mixed $params 
     * @return array the catmatch record 
     */
    public function updateAdgroupCatMatch($user_id , $params, $isAutodrive = false){
        $res = $this->_api->SimbaAdgroupCatmatchUpdateRequest($params); 
        $catmatch = (array) $res["adgroupcatmatch"];
        
        if($catmatch) {
        	$this->addLog($catmatch['adgroup_id'], $catmatch['campaign_id'], 
        			($isAutodrive ? AdgroupLogActions::AUTO_UPDATE_CATMATCH : AdgroupLogActions::MANUAL_UPDATE_CATMATCH),
        			$catmatch['max_price'], json_encode($catmatch)
        	);
        	
	        $catmatch['user_id'] = $user_id;
	        $ret = M("catmatch")->add( $catmatch , array() , true);
        }
        return $catmatch;
    }
    
    /**
     * 切换开车类型到收到
     * @param int $user_id
     * @param array(k=>v) $adgroup
     * @param bool $isAuto Autho drive or not
     * @return bool , true 表示切换成功， false表示切换失败
     * 
     */
    public function switchAdgroupToManual($user_id, $adgroup, $isAuto = false){
    	$adgroup_id = $adgroup['adgroup_id'];
        $whr = array(
                'user_id' => $user_id,
                'adgroup_id' => $adgroup_id
        );
        //1 . delete auto_product_queue record
        // $ret = M("auto_pro_product_queue")->where($whr)->delete();
        //2 . update adgroups drive_type field
        $ret = $this->where($whr)->save( array('drive_type' => AdgroupModel::DRIVE_TYPE_MANUAL) );
        $this->addLog($adgroup['adgroup_id'], $adgroup['campaign_id'],
        		AdgroupLogActions::SWITCH_DRIVE_TYPE, 
        		($isAuto ? self::DRIVE_TYPE_AUTO : self::DRIVE_TYPE_MANUAL) );
        return $ret;
        
    }
    
    /**
     * switch the adgroup to auto drive 
     * @param $user id 
     * @param DbRecord of adgroup , 推广组数据库记录
     * @param $type , 开车模式 ： 1 - 智能 2 - 引流 3 - 省油
     * @param  $strategy  ，自动开车模型类
     * @return mixed  ， 一条auto_product_queue的开车记录 , 切换失败返回false
     */
    public function switchAdgroupToAuto($user_id ,  $adgroup , $type = 1 ,$default_price=0,  $strategy = DEFAULT_AUTO_ENGINE ){
        //$adgroup = $this->getAdgroupByAdgroupId($user_id, $adgroup_id);
        $auto_pq_product = array();
        $auto_pq_product['product_id'] = $adgroup['num_iid'];
        $auto_pq_product['user_id'] = $user_id;
        $auto_pq_product['max_expense'] = 0;
        $auto_pq_product['strategy'] =  $strategy;
        $auto_pq_product['progress'] = 100;
        $auto_pq_product['status'] = 2;
        $auto_pq_product["msg"] = '';
        $auto_pq_product['type'] = $type;
        $creativeMdl = new CreativeModel();
        $creatives = $creativeMdl->getCreativesByAdgroupId($user_id, $adgroup['adgroup_id'] , true);     
        $order = 1;
        foreach( $creatives as $creative ){
            if(substr($creative['img_url'],-8)=='_sum.jpg'){
                $creative['img_url']=substr($creative['img_url'], 0, -8);
            }
            $title_ix = 'title' . $order;
            $img_ix = 'img_url' . $order;
            $auto_pq_product[ $title_ix ] = $creative['title'];
            $auto_pq_product[ $img_ix ] = $creative['img_url'];
            $order++;
        }
        $auto_pq_product['need_confirm'] = 0;
        $auto_pq_product['campaign_id'] = $adgroup['campaign_id'];
        $auto_pq_product['default_price'] = $default_price * 100;
        $auto_pq_product['addtime'] = time();
        $auto_pq_product['updated'] = time();
        $auto_pq_product['adgroup_id'] = $adgroup['adgroup_id'];
        
        $pqMdl = new ProductQueueModel();
        $ret = $pqMdl->addAllOnDupUpdate(array($auto_pq_product), array(), array('product_id', 'campaign_id', 'addtime'));
//         $ret = M("auto_pro_product_queue")->add($auto_pq_product , array() , true);
        
        if($ret){
            //udpate adgroup record
            $whr = array(
                    'user_id' => $user_id,
                    'adgroup_id' => $adgroup['adgroup_id']
            );
            $this->where( $whr )->save( array( 'drive_type' => AdgroupModel::DRIVE_TYPE_AUTO ) );
            
            $this->addLog($adgroup['adgroup_id'], $adgroup['campaign_id'], 
            			AdgroupLogActions::SWITCH_DRIVE_TYPE, self::DRIVE_TYPE_AUTO);
            return $auto_pq_product;
        }else{
            return $ret;
        }
    }
    
    /**
     * set adgroup auto drive 
     * @param int $user id 
     * @param DbRecord $adgroup , 推广组数据库记录
     * @param int $type , 开车模式 ： 1 - 智能 2 - 引流 3 - 省油
     * @param string $strategy  ，自动开车模型类
     * @return bool 
     */
    public function setAdgroupAuto($user_id ,  $adgroup , $type = 1 ,$max_price=NULL) {
        //$adgroup = $this->getAdgroupByAdgroupId($user_id, $adgroup_id);
        $pqProduct = M("auto_pro_product_queue")->where('product_id='.$adgroup['num_iid'] . ' AND campaign_id=' . $adgroup['campaign_id'])->find();
        if($pqProduct['type'] == $type&&($max_price!=NULL&&$pqProduct['default_price']==$max_price )) // 无需更改
        	return true;
        
        $data['type'] = $type;
        $data['updated'] = time();
        if($max_price!=NULL){
        	$data['default_price'] = $max_price*100;
        }
        $ret = M("auto_pro_product_queue")->where('product_id='.$adgroup['num_iid'] . ' AND campaign_id=' . $adgroup['campaign_id'])->save($data);
        
        if($ret) // 记录log
        	$this->addLog($adgroup['adgroup_id'], $adgroup['campaign_id'],
        			AdgroupLogActions::SWITCH_AUTO_TYPE, $type, json_encode(array('type'=>$pqProduct['type'])));
        return $ret;
    }
    
    /**
     * get the catmatch of one adgroup
     * int user id
     * int catmatch
     * return mixed
     */
    public function getAdgroupCatMatch($user_id , $adgroup_id){
    
        $whr = array( "user_id" => $user_id , "adgroup_id" => $adgroup_id);
        $catmatch = M('catmatch')->where($whr)->find();
        if(!$catmatch){
            $params = array(
                'adgroup_id' => $adgroup_id
            );
            $res = $this->_api->SimbaAdgroupCatmatchGetRequest($params); 
            $catmatch = (array) $res["adgroupcatmatch"];
            $catmatch['user_id'] = $user_id;
            $catmatch['updated_time'] = date('Y-m-d H:i:s');
            $catmatchMdl = D("catmatch");
            $ret = $catmatchMdl->add( $catmatch , array() , true);
        }
        return $catmatch;
    }
    
    /**
     * 根据ID获取推广组.
     * 
     * @param int $user_id
     * @param int $adgroup_id
     * @param boolean $withSummary
     * @param string $from
     * @param string $to
     * @return boolean|Ambigous <unknown, mixed, boolean, NULL, multitype:>
     */
    public function getAdgroupByAdgroupId($user_id , $adgroup_id , $withSummary = false, $from=null, $to=null){
    
        $whr = array(
            'user_id' => $user_id,
            'adgroup_id' => $adgroup_id
        );
        
        $adgroup = $this->where($whr)->find();
        
        if(!$adgroup){
            return false;
        }

        return $adgroup;
    }
    
    /**
     * 得到用户所有的adgroups,只从本地读
     *   
     * @param int $user_id 
     * @param string $drive_type 下列三者之一: '', 'manual', 'auto'. TODO 加上 混合动力: 'mixed' => 2
     * bool , if retrieve the auto process adgroups
     */
	public function getAdgroupsByUser($user_id, $drive_type = '', $keyword = '' ,$currentPage = 1 , $pageSize = 20  , $status = ''){
        $whr = " where a.user_id= $user_id ";
        if(!empty($drive_type) && $drive_type != 'all') {
        	$dtype=$drive_type == 'manual' ? 0 : 1;
        	$whr.=" and a.drive_type = $dtype" ;
        }
        if( !empty($keyword) ){
            $whr.=" and a.title like '%$keyword%' ";
        }
        
        if( !empty($status) && $status != 'all' ){
            $whr.=" and a.online_status = '$status' ";
            if( $status == 'online' ) $whr.=" and a.offline_type = 'online'";
        }
        $offset=($currentPage-1)*$pageSize;
        $from = $from ? $from : strftime('%Y-%m-%d' , date2time(-7) );
		$to = $to ? $to : strftime('%Y-%m-%d' , date2time(-1) );
		//$whr.=" and ra.date <= '$to'  AND  ra.date >= '$from'";
		$sql = "select se.*,a.* from (SELECT a1.*, SUM(ra.direct_pay + ra.indirect_pay)/100 AS sales,SUM(ra.click) AS click
                      FROM rpt_adgroup ra
                      RIGHT JOIN adgroups a1 ON ra.adgroup_id = a1.adgroup_id 
                      where a1.user_id= $user_id  and ra.date <= '$to'  AND  ra.date >= '$from' GROUP BY a1.adgroup_id) as se
                      RIGHT JOIN adgroups a on a.adgroup_id=se.adgroup_id 
                      $whr
                       order by sales desc, click desc 
		  				LIMIT $offset,$pageSize";
		$adgroups_r = $this->query($sql);
		$adgroups=array();
		foreach($adgroups_r as $ad){
			$adgroups[$ad['adgroup_id']]=$ad;
		}
        
    //    $adgroups = $this->where($whr)->limit($pageSize)->page($currentPage)->select( array( "assoc_key" => true ) );
        
        $status_info = array(
            0 => '正常',
            1 => '自动更新中',
            2 => '暂停推广',
            -1 => '等待确认提交'  
        );
        if($adgroups) {
	        foreach($adgroups as &$ad){
					$ad['drive_type_str'] = $ad['drive_type'] == 0 ? '手动开车' : '自动开车';
	                if( $ad['online_status'] == 'online' ){
	                    $ad['status_str'] = $status_info[$ad['status']];
	                }else{
	                    $ad['status_str'] = $ad['offline_type'];
	                }
	            
	        }
	        return $adgroups; 
        } else {
        	return array();
        }
     }
     
     /**
      * 获取推广组可以投放的所有通投位置或者某个推广组的通投位置
      * @param int/string/array $adgroup_id, 推广组ID，为0的时候表示返回所有可以投放的投放位置，为字符串每个id用逗号隔开，为数组时为1D数组，
      * 									   查询多个推广组的通投位置设置时候，必须注意所有ID必须在同一个推广计划ID下
      * @param int $campaign_id, 推广组所属于推广计划ID，当查询某个推广组的投放位置设置时此值必须得设置
      * @return mixed adgroup_place， 返回包含以下结构之一为元素的2D数组
      * @exception TopClientException 	
      * 	返回所有可以投放位置时结构如下：
      * 		place_id	 Number	 否	22	位置标识
	  *			name	 String	 否	淘宝网/阿里旺旺/每日焦点掌柜热卖	位置名称
	  *			create_time	 Date	 否	2000-01-01 00:00:00	创建时间
	  *			last_update_time	 Date	 否	2000-01-01 00:00:00	最后修改时间
	  *
	  *		返回某个推广组已经投放的位置时结构如下
	  *			nick	 String	 否	zcztest001	主人昵称
	  *			campaign_id	 Number	 否	1232323	推广计划ID
	  *			adgroup_id	 Number	 否	23434	推广组ID
	  *			place_name	 String	 否	淘宝网/阿里旺旺/每日焦点掌柜热卖	位置名称
	  *			is_default_price	 Number	 否	1	是否使用默认出价，0-不用；1-使用；
	  *			max_price	 Number	 否	23	出价
	  *			create_time	 Date	 否	2000-01-01 00:00:00	创建时间
	  *			modified_time	 Date	 否	2000-01-01 00:00:00	修改时间
	  *			place_id	 Number	 否	12345	位置标识
      */
     public function getPlacesOfAdgroupById($adgroup_ids = 0,$campaign_id = 0){     	
     	if($adgroup_ids && $campaign_id){
     		if(is_array($adgroup_ids)){
     			$adgroup_ids = implode(',' , $adgroup_ids);
     		}
     		
     		$params = array(
     			'adgroup_ids' => $adgroup_ids,
     			'campaign_id' => $campaign_id 
     		);
     		
     		$res = $this->_api->SimbaNonsearchAdgroupplacesGetRequest($params);
     		$adgroups_places = object_to_array( $res['adgroup_place_list']->a_d_group_place );
     		return $adgroups_places;
     	}else{
     		$cache_key = 'all_adgroups_places';
     		//$this->ca
     			$res = $this->_cache->get($cache_key);

     			$all_places = json_decode($res , true);
     		if(!$res){
     			$res = $this->_api->SimbaNonsearchAllplacesGetRequest();
     			$all_places = object_to_array( $res['place_list']->place );
     			$this->_cache->set($cache_key , json_encode($all_places) , 3600 * 24 );
     		} 
     		
     		return $all_places;
     		
     	}
     	
     }
     
     /**
      *  新增一个或者多个个推广组的nonsearch投放
      *  @param int $campaign_id, 推广组ID，增加的adgroup的ID必须全部属于本推广计划
      *  @param mixed , $adgroups_places ，一个包含多个ADGroupPlace的2D数组，注意adgroup_id必须属于参数一的campaign_id
      *  				[{“adgroupId”:102232,”placeId”:22},{“adgroupId”:102232,” placeId”:20} ]
      *  @return ADGroupPlace [] ，以此
      *  
      *  ADGroupPlace结构  :
      *  http://api.taobao.com/apidoc/dataStruct.htm?path=cid:46-dataStructId:20624-apiId:21257-invokePath:adgroup_place_list
      */
     
     public function addAdgroupsNonSearchs($campaign_id, $adgroup_places){	
     	$params = array(
     		'campaign_id' => $campaign_id,
     		'adgroup_places_json' => json_encode($adgroup_places)
     	);
     	
     	$res = $this->_api->SimbaNonsearchAdgroupplacesAddRequest($params);
     	     	
     	$adgroups_places = $res['adgroup_place_list']->a_d_group_place;
     	
     	return $adgroups_places;
     }
     
     /**
      *  删除一个或者多个个推广组的nonsearch投放
      *  @param int $campaign_id, 推广组ID，增加的adgroup的ID必须全部属于本推广计划
      *  @param mixed , $adgroups_places ，一个包含多个ADGroupPlace的2D数组，注意adgroup_id必须属于参数一的campaign_id
      *  				[{“adgroupId”:102232,”placeId”:22},{“adgroupId”:102232,” placeId”:20} ]
      *  @return ADGroupPlace [] ，以此
      *
      *  ADGroupPlace结构  :
      *  http://api.taobao.com/apidoc/dataStruct.htm?path=cid:46-dataStructId:20624-apiId:21257-invokePath:adgroup_place_list
      */
      
     public function delAdgroupsNonSearchs($campaign_id, $adgroup_places){
     	$params = array(
     			'campaign_id' => $campaign_id,
     			'adgroup_places_json' => json_encode($adgroup_places)
     	);
     
     	$res = $this->_api->SimbaNonsearchAdgroupplacesDeleteRequest($params);
     
     	$adgroups_places = $res['adgroup_place_list']->a_d_group_place;
     
     	return $adgroups_places;
     }

     /**
      *  修改一个或者多个个推广组的nonsearch投放
      *  @param int $campaign_id, 推广组ID，增加的adgroup的ID必须全部属于本推广计划
      *  @param mixed , $adgroups_places ，一个包含多个ADGroupPlace的2D数组，注意adgroup_id必须属于参数一的campaign_id
      *  				[{“adgroupId”:102232,”placeId”:22 , "maxPrice" : 342, "isDefaultPrice" : 0},{“adgroupId”:102232,” placeId”:20} ]
      *  @return ADGroupPlace [] ，以此
      *
      *  ADGroupPlace结构  :
      *  http://api.taobao.com/apidoc/dataStruct.htm?path=cid:46-dataStructId:20624-apiId:21257-invokePath:adgroup_place_list
      */
     
     public function updateAdgroupsNonSearchs($campaign_id, $adgroup_places){
     	$params = array(
     			'campaign_id' => $campaign_id,
     			'adgroup_places_json' => json_encode($adgroup_places)
     	);

     	$res = $this->_api->SimbaNonsearchAdgroupplacesUpdateRequest($params);
     	 

     	$adgroups_places = $res['adgroup_place_list']->a_d_group_place;
     	 
     	return $adgroups_places;
     }
     
     
     /**
      * 修改定向投放通用投放位置的状态
      * @param campaign_id , int
      * @param mix array $data
      * etc : [ {“adgroupId”:102232,” nonsearchStatus”:1}, {“adgroupId”:102237,” nonsearchStatus”:0} ]
      * 1表示开启，0表示关闭
      * @return mixed ADGroupPlace [] @see self::updateAdgroupsNonSearchs
      * 
      */
     
     public function updateAdgroupNonSearchStatus($campaign_id , $adgroup_nonsearch_status){
         $params = array(
              			'campaign_id' => $campaign_id,
              			'adgroupid_nonsearchstate_json' => json_encode($adgroup_nonsearch_status)
         );
         $res = $this->_api->SimbaAdgroupNonsearchstatesUpdateRequest($params);
         $adgroups_places = $res['adgroup_place_list']->a_d_group_place;
         return $adgroups_places;
     }
      

     /**
      * 修改定向投放通用投放位置的出价
      * @param campaign_id , int
      * @param mix array $data
      * etc : [{“adgroupId”:102232,”nonsearchMaxPrice”:22,“isNonsearchDefaultPrice”:true}, {“adgroupId”:102232,”nonsearchMaxPrice”:20,”isNonsearchDefaultPrice”:false}]
      * 	
      * @return mixed ADGroupPlace [] @see self::updateAdgroupsNonSearchs
      *
      */
      
     public function updateAdgroupNonsearchDefaultPrice($campaign_id , $adgroup_nonsearch_status){
         $params = array(
                 'campaign_id' => $campaign_id,
                 'adgroupid_price_json' => json_encode($adgroup_nonsearch_status)
         );
         $res = $this->_api->SimbaAdgroupNonsearchpricesUpdateRequest($params);
         $adgroups_places = $res['adgroup_place_list']->a_d_group_place;
         return $adgroups_places;
     }
     
     
    /**
     *  get user all compaign inforamtoin
     *  
     * @param int $user_id
     * @param int $campaign_id
     * @return mixed array
     */
    public function getCampaignsAdgroups($user_id , $campaign_id , $withSummary=false , 
    		$from=null , $to=null, $adgroupIdAsKey = false, $page = 0 , $pageSize = 0, $sort = array(), $where = array()){
        $platform = array('summary','pc', 'wireless');
    	
        $whr = array("user_id" => $user_id , "campaign_id" => $campaign_id);
        $whr = array_merge($whr, $where);
        if( $page && $pageSize ){
            $this->page($page)->limit($pageSize);
        }
        if($sort && isset($sort['sort']) && $sort['sort'] == 'status') {
            $adgroups = $this->where($whr)->order('online_status '. $sort['asc'])->select(array('assoc_key'=>$adgroupIdAsKey));
        } else {
            $adgroups = $this->where($whr)->select(array('assoc_key'=>$adgroupIdAsKey));
        }

        if($adgroups === false) {
        	throw_exception('数据库错误: ' . $this->getDbError());
        }

        if($withSummary){
        	$sortedAdgroups=array();
            $indicators = '';
            $rptAdgroupMdl = new RptAdgroupModel();
            $stats = $rptAdgroupMdl->getAllAdgroupStat($user_id , 
            		array_column($adgroups, 'adgroup_id'), $indicators , $from , $to , implode(',', $platform), $sort);
            if($adgroups){
                foreach ($platform as $p) {
                    foreach($stats[$p] as $adgroup_id => $stat){
                        if(!isset($sortedAdgroups[$adgroup_id]))
                            $sortedAdgroups[$adgroup_id] = $adgroups[$adgroup_id];
                        $sortedAdgroups[$adgroup_id][$p] = $stat;
                    }
                }
                // foreach($adgroups as $key=>$ad){
                //     if(!isset($sortedAdgroups[$key])){
                //         $sortedAdgroups[$key]=$ad;
                //         $sortedAdgroups[$key]["summary"] = null;
                //     }
                // }
            }
        }else{
        	$sortedAdgroups=$adgroups;
        }
        return $sortedAdgroups;
    }

    public function getUserAdgroupsAll($user_id, $adgroupIdAsKey = false, $where = array())
    {
        $whr = array("user_id" => $user_id);
        if($where)
           $whr = array_merge($whr, $where); 
        $adgroups = $this->where($whr)->select(array('assoc_key'=>$adgroupIdAsKey));
        return $adgroups;
    }    

     /**
      * 过滤一个推广计划下的推广组，可以过滤一下条件
      * pv -- 有展现的推广组
      * sales -- 有销售的推广组
      * cost  -- 有花费的推广组
      * $user_id int taobao user id
      * $campaign_id int taobao campaign id
      * $filter mixed  array or string , 可以是 pv,sales,cost
      * $page int , 当前页面
      * $pageSize int , 每页大小
      */

     public function getCampaignAdgroupsWithFilter( $user_id , $campaign_id, $filters = array() , $from , $to , $page = 1 , $pageSize = 10){
		if(!$from || !$to ) {
			throw_exception('需要输入起始时间和结束时间');
		}

		$filters_mapper = array(
				'pv' => ' impressions > 0',
				'click' => ' click > 0 ',
				'cost' => ' cost > 0 ',
                'sales' => ' sales > 0 ',
				'fav' => ' (fav_shop_count > 0 OR fav_item_count > 0) '
		);

        $order_mapper = array(
            'pv' => ' ORDER BY impressions DESC',
            'sales' => ' ORDER BY sales DESC',
            'cost' => ' ORDER BY cost DESC',
            'fav' => ' ORDER BY fav_count DESC'
        );

        // get all adgroup ids in this campaign
        $adgroup_ids = M('adgroups')->where( 'campaign_id =' . $campaign_id)->getField('adgroup_id', true);
		$filter_sql = '';
        $order_sql = '';
		if($filters) {
			$tmp_sql = array();
			$filters = is_array($filters) ? $filters : explode(',' , $filters);
			foreach( $filters as $filter){
				if( isset($filters_mapper[$filter]) ){
					$tmp_sql[] = $filters_mapper[$filter];
				}
			}
			$filter_sql = implode(' AND ' , $tmp_sql);
            
            foreach( $filters as $filter){
				if( isset($order_mapper[$filter]) ){
					$order_sql = $order_mapper[$filter];
				}
            }
		}
        //$whrIds = 'r.campaign_id = ' . $campaign_id;
        if( !empty($adgroup_ids) ){
            $whrIds1 = 'r.adgroup_id in (' . implode(',' , $adgroup_ids) . ')';
            $whrIds2 = 'a.adgroup_id in (' . implode(',' , $adgroup_ids) . ')';
        }else{
            return array();
        }
        $sql = "
            SELECT * FROM adgroups a LEFT JOIN ( 
                SELECT r.campaign_id,r.adgroup_id,
                SUM(impressions) AS impressions,SUM(click) AS click,SUM(cost)/100 AS cost,
                SUM(direct_pay + indirect_pay)/100 AS sales,
                SUM(direct_pay)/100 AS direct_pay,SUM(indirect_pay)/100 AS indirect_pay,
                SUM(direct_pay_count) AS direct_pay_count,
                SUM(indirect_pay_count) AS indirect_pay_count,
                SUM(direct_pay_count + indirect_pay_count) AS pay_count,
                SUM(fav_shop_count) AS fav_shop_count,
                SUM(fav_item_count) AS fav_item_count,
                SUM(fav_shop_count + fav_item_count) AS fav_count,
                100*SUM(direct_pay_count + indirect_pay_count)/SUM(click) AS cvr,
                100*SUM(click)/SUM(impressions) AS ctr, 
                SUM(cost)/100/SUM(click) AS cpc, 
                10*SUM(cost)/SUM(impressions) AS cpm,
                AVG(avgpos) AS avgpos, 
                SUM(direct_pay + indirect_pay)/SUM(cost) AS roi
                FROM rpt_adgroup r 
                WHERE $whrIds1 AND `date` BETWEEN '$from' AND '$to' 
                GROUP BY r.adgroup_id
            ) AS rk ON rk.adgroup_id = a.adgroup_id WHERE $whrIds2";
		if( $filter_sql ){
			$sql .= " AND " . $filter_sql;
		}
		//$sql .= " GROUP BY r.adgroup_id ";
        $sql .= $order_sql;
        $left = ($page - 1) * $pageSize;
        $right = $page * $pageSize;
        $sql .= " LIMIT $left, $right";
		$res = $this->query( $sql );
		return $res;
     }

     /**
      * 添加一个新的adgroup到直通车(会自动创建一个creative), 记录他们的log, 并保存到本地DB.
      *  
      * @param int $user_id 
      * @param array(k=>v) $adgroup adgroup data
      * @param boolean $isAutodrive
      * @return int , adgroup id
      */
     public function addAdgroup($user_id , $adgroup, $isAutodrive = false){
        // init a api request 
        $resp = $this->_api->SimbaAdgroupAddRequest($adgroup);
        $data = (array) $resp["adgroup"];
        $adgroup_id = $data["adgroup_id"];   
        
        $this->addLog($adgroup_id, $data['campaign_id'], 
        		($isAutodrive ? AdgroupLogActions::AUTO_ADD : AdgroupLogActions::MANUAL_ADD),
        		0, json_encode($data)
        );
        
        //add this adgroup to local storage
        $data["drive_type"] = ($isAutodrive ? self::DRIVE_TYPE_AUTO : self::DRIVE_TYPE_MANUAL);
        $data["title"] = $adgroup["title"];
        $data["img_url"] = $adgroup["img_url"];
        $data["user_id"] = $user_id;
		$data["maintained_date"] = date("Y-m-d");
		if(isset($adgroup['status'])) 
			$data['status'] = $adgroup['status'];
        $result = $this->add($data , array() , true);
        

        $creativeMdl = new CreativeModel();
        // 先将添加adgroup时自动添加到creative同步下来
        $creativeMdl->syncCreatives($user_id, $adgroup_id, $isAutodrive);
        
        return $adgroup_id;
    }    
    
    
    /* check if this product has been ad 
     * param int , product_id
     */
     public function hasAdgroup( $product_id , $campaign_id){
        return $this->where("num_iid = " . $product_id.' and campaign_id='.$campaign_id)->find();
     }
     
     /**
      * 只更改给定adgroup的数据库信息, 无需提交API. 更改成功后会记录log.
      * 
      * @param int $user_id
      * @param array|int $adgroup 一条adgroup记录或者adgroup_id
      * @param array $data 要更新的数据, array(k=>v)
      * @param boolean $isAutodrive
      * @return int 返回影响的记录条数.
      * @throws NewzanException 当给定的adgroup不存在时抛出异常. 
      */
     public function updateAdgroupDB($user_id, $adgroup , $data, $isAutodrive = false){
     	if(!is_array($adgroup)) {
     		$adgroup = $this->getAdgroupByAdgroupId($user_id, $adgroup,false);
     	}
     	if($adgroup) {
     		$adgroup_id = $adgroup['adgroup_id'];
	     	$ret = $this->where( array("user_id" => $user_id , "adgroup_id" => $adgroup_id) )->save($data);
	     	if($ret) {
		     	$this->addLog($adgroup_id, $adgroup['campaign_id'],
		     			($isAutodrive ? AdgroupLogActions::AUTO_UPDATE : AdgroupLogActions::MANUAL_UPDATE),
		     			0, json_encode($data)
		     	);
		     	
	     	} 
	     	return $ret;
     	} else {
     		throw_exception('给定的推广组不存在.', 'NewzanException', RetStatus::PARAM_ERR);
     	}
     }
     
     /**
      *  更新一个推广组的信息. 主要为 'default_price' 和 'online_status'. 并记录log.
      *  
      * @param int $user_id,  user_id
      * @param int $adgroup_id, adgroup_id
      * @param array(k=>v) $data, information to be modifed. 主要为 'default_price' 和 'online_status'
      * @param boolean $isAutodrive
      * @return array API返回的新的推广组.
      */
      public function updateAdgroup($user_id, $adgroup_id , $data, $isAutodrive = false){
        // init a api request 
        $data["adgroup_id"] = $adgroup_id;
        $resp = $this->_api->SimbaAdgroupUpdateRequest($data);
        $adgroup = (array) $resp["adgroup"];
        if($adgroup) {
        	// 记录log
        	$data['modified_time'] = isset($adgroup['modified_time']) ? $adgroup['modified_time'] : date('Y-m-d H:i:s');
        	$this->addLog($adgroup['adgroup_id'], $adgroup['campaign_id'], 
        			($isAutodrive ? AdgroupLogActions::AUTO_UPDATE : AdgroupLogActions::MANUAL_UPDATE),
        			0, json_encode($data)
        	);
	        //update local storage
        	if(isset($data['online_status']))
        		$data['status'] = ($data['online_status'] == 'offline' ? 2 : 0);
        	unset($data['adgroup_id']); //  这个不需要保存到note中
	        $this->where( array("user_id" => $user_id , "adgroup_id" => $adgroup_id) )->save($data);
	        
	        // 如果存在auto_pro_product_queue表中, 则更新其状态为已经confirm
	        if(isset($data['online_status']) && $data['online_status'] == 'online') {
	        	$whr = array(
	        			'user_id' => $user_id,
	        			'product_id' => $adgroup['num_iid'],
	        			'campaign_id' => $adgroup['campaign_id'],
	        			'need_confirm'=> 1,
	        			'status' => 2,
	        	);
	        	M('auto_pro_product_queue')->where( $whr )->save(array('need_confirm'=>2));
	        }
        }
        return $adgroup;
      }
      
      /**
       * 将续费购买了手动版，但是还存在的自动推广组转为手动开车。并给用户发送提醒。
       * @param int $userId 用户ID
       * @return void
       */
      public function checkManualUserAutoAds($userId) {
      	$autoAdgroups = $this->where(array(
    			'user_id' => $userId, 
    			'drive_type' => self::DRIVE_TYPE_AUTO
      	))->select();
      	if($autoAdgroups) {
      		foreach($autoAdgroups as $adgroup) {
      			$this->switchAdgroupToManual($user_id, $adgroup, true);
      		}
      		$title = "续费购买了手动版，但是还存在自动推广组";
      		$content = 
<<<EOF
				<p>亲，</p>
				<p>非常感谢您的信任又继续订购了我们的飞车服务。
					但是您最近续费购买的版本不支持自动开车，而系统检测到您还有一些自动开车推广组。
					系统已经自动将其转化为手动开车了。待您购买了自动版之后，您可以通过“手动转自动”功能将其再设为自动。</p>
EOF;
      		// 发送站内信。
      		MessageModel::send($userId, $title, $content, 'WARN', 'HTML');
      	}
      }
      
      /**
       * 添加一条log记录.
       *
       * @see AdgroupLogActions
       * @param int $adgroupId
       * @param int $campaignId
       * @param int $action 使用AdgroupLogActions::XX常量. 示例: AdgroupLogActions::AUTO_ADD
       * @param int $newVal 新整型值
       * @param string $note 字符串备注. 例如可以给定为关键词修改后的状态json: {max_price: NNN, match_scope: NNN, qscore: NNN}
       * @return false|int ThinkkPHP添加记录的返回值. 失败返回false, 否则返回key.
       */
      public function addLog($adgroupId, $campaignId, $action, $newVal = 0, $note = '') { // $oldVal, 
      	return $this->_getLogMdl()->add(array(
      			'adgroup_id' => $adgroupId,
      			'campaign_id' => $campaignId,
      			'action' => $action,
//       			'old_int_val' => $oldIntVal,
      			'new_int_val' => $newVal,
      			'note' => $note,
      	));
      }
      
      
      /**
       * 解释一条adgrouop log 的note记录
       * @param 一条adgroup的log记录
       * @return mixed 
       * @see parent::getLogs
       * 
       */
      public function readLog($log, $simple_disp){
      	$detailed_log = parent::readLog($log, $simple_disp);
      	//解释note记录
      	$note = $detailed_log['action_note'];
      	$ad_disp = $simple_disp ? '' : '[ID: ' . $log['adgroup_id'] . ']';
      	
      	$action_note = '';
      	switch($log['action']) {
      		case AdgroupLogActions::AUTO_ADD:
      		case AdgroupLogActions::MANUAL_ADD:
      			$action_note = "添加推广组$ad_disp";
      			break;
      		case AdgroupLogActions::AUTO_DEL:
      		case AdgroupLogActions::MANUAL_DEL:
      			$action_note = "删除推广组$ad_disp";
      			break;
      		case AdgroupLogActions::AUTO_PAUSE:
      		case AdgroupLogActions::MANUAL_PAUSE: 
      			$action_note = "暂停推广组$ad_disp";
      			break;
      		case AdgroupLogActions::AUTO_OPEN:
      		case AdgroupLogActions::MANUAL_OPEN:
      			$action_note = "开启推广组$ad_disp";
      			break;
      		case AdgroupLogActions::AUTO_UPDATE:
      		case AdgroupLogActions::MANUAL_UPDATE:
      			if( isset($note['default_price']) ) {
      				$action_note .= "修改推广组{$ad_disp}默认出价为￥" . $note['default_price']/100.0  ;
      			}
      			if( isset($note['online_status']) ) { //  || isset($note['num_iid'])
      				$online_str = $note['online_status'] == 'online' ? '开启' : '暂停';
      				$action_note .= isset($note['default_price']) ? ", 并{$online_str}推广组" : "{$online_str}推广组{$ad_disp}";
      			}
//       			$action_note = 'safsfsdaf';
      			break;
      		case AdgroupLogActions::AUTO_UPDATE_CATMATCH:
      		case AdgroupLogActions::MANUAL_UPDATE_CATMATCH:
      			$action_note = "修改推广组{$ad_disp}类目出价为￥" . $detailed_log['action_value'] /100.0  ;
      			break;
      		case AdgroupLogActions::SWITCH_DRIVE_TYPE:
      			$action_note = "切换推广组{$ad_disp}为" . ($detailed_log['action_value'] == self::DRIVE_TYPE_AUTO ? '自动开车' : '手动开车');
      			break;
      		case AdgroupLogActions::SWITCH_AUTO_TYPE:
      			$autoTypeNames = C('AUTO_DRIVE_TYPE_NAMES');
      			$action_note = "切换自动推广组{$ad_disp}为" . $autoTypeNames[$detailed_log['action_value']];
      	}
      	$detailed_log['action_note'] = $action_note;
      	return $detailed_log;
      }
      
      
      /**
       * @return Model
       */
      protected function _getDeletedMdl() {
      	if($this->_deletedMdl == null) {
      		$this->_deletedMdl = M('adgroups_deleted');
      	}
      	return $this->_deletedMdl;
      }

      /**
       * @return Model
       */
      protected function _getLogMdl() {
      	if($this->_logMdl == null) {
      		$this->_logMdl = M('adgroups_log');
      	}
      	return $this->_logMdl;
      }
}    

/**
 * 推广组操作类型常量
 * 
 * @author weiping
 */
class AdgroupLogActions {
	/** 自动添加 */
	const AUTO_ADD = 0;
	/** 自动删除 */
	const AUTO_DEL = 1;
	/** 自动暂停 */
	const AUTO_PAUSE = 2;
	/** 自动启动 */
	const AUTO_OPEN = 3;
	/** 自动更新推广组 */
	const AUTO_UPDATE = 4;
	/** 自动更新推广组类目出价 */
	const AUTO_UPDATE_CATMATCH = 5;
	/** 手动添加 */
	const MANUAL_ADD = 10;
	/** 手动删除 */
	const MANUAL_DEL = 11;
	/** 手动暂停 */
	const MANUAL_PAUSE = 12;
	/** 手动启动 */
	const MANUAL_OPEN = 13;
	/** 手动更新推广组 */
	const MANUAL_UPDATE = 14;
	/** 手动更新推广组类目出价 */
	const MANUAL_UPDATE_CATMATCH = 15;
	/** 自动/手动档切换 */
	const SWITCH_DRIVE_TYPE = 16;
	/** 切换自动开车类型 */
	const SWITCH_AUTO_TYPE = 17;
	
}
?>
